#include "handlers/http_handler.hpp"
#include "database/user_dao.hpp"
#include "database/file_dao.hpp"
#include "utils/token.hpp"
#include "utils/crypto.hpp"
#include "utils/file_utils.hpp"
#include "utils/oss_client_manager.hpp"
#include "common/config.hpp"
#include "common/response.hpp"
#include "common/debug.hpp"
#include "utils/rabbitmq_client.hpp"
#include <nlohmann/json.hpp>
#include <workflow/WFTaskFactory.h>
#include <workflow/WFFacilities.h>
#include <workflow/HttpUtil.h>
#include <iostream>



using json = nlohmann::json;

// --- 辅助函数：验证Token并获取用户实体 ---
static std::optional<User> verify_token_and_get_user(WFHttpTask* task) {
    const auto* req = task->get_req();
    protocol::HttpHeaderCursor cursor(req);
    std::string auth_header;
    std::string token;

    if (cursor.find("Authorization", auth_header) && auth_header.rfind("Bearer ", 0) == 0) {
        token = auth_header.substr(7);
    }

    if (token.empty()) {
        task->get_resp()->set_status_code("401");
        task->get_resp()->append_output_body(Response::jsonError("Authorization header is missing."));
        return std::nullopt;
    }

    std::string username = Token::extractUsername(token);
    if (username.empty()) {
        task->get_resp()->set_status_code("401");
        task->get_resp()->append_output_body(Response::jsonError("Invalid token."));
        return std::nullopt;
    }
    
    auto user_opt = UserDao::getUserByUsername(username);
    if (!user_opt) {
        task->get_resp()->set_status_code("401");
        task->get_resp()->append_output_body(Response::jsonError("User in token not found."));
    }
    return user_opt;
}

// 用于存储解析出的每一个部分
struct MultipartPart {
    std::map<std::string, std::string> headers;
    std::string content;
};

// 解析函数
static std::vector<MultipartPart> parse_multipart_body(const std::string& body, std::string boundary) {
    std::vector<MultipartPart> parts;
    boundary = "--" + boundary;

    size_t start_pos = 0;
    while ((start_pos = body.find(boundary, start_pos)) != std::string::npos) {
        start_pos += boundary.length();
        if (body.substr(start_pos, 2) == "--") {
            break; 
        }
        start_pos += 2; // 跳过 \r\n

        auto headers_end = body.find("\r\n\r\n", start_pos);
        if (headers_end == std::string::npos) break;

        auto next_boundary_pos = body.find(boundary, headers_end);
        if (next_boundary_pos == std::string::npos) break;

        MultipartPart part;
        
        // --- 核心修正：截取内容时，减去末尾的 \r\n (长度为 2) ---
        part.content = body.substr(headers_end + 4, next_boundary_pos - (headers_end + 4) - 2);

       // 解析头部信息
        std::string headers_str = body.substr(start_pos, headers_end - start_pos);
        size_t h_start = 0;
        while ((h_start = headers_str.find("Content-Disposition:", h_start)) != std::string::npos) {
            auto h_end = headers_str.find("\r\n", h_start);
            std::string line = headers_str.substr(h_start, h_end - h_start);

            auto name_pos = line.find("name=\"");
            if (name_pos != std::string::npos) {
                name_pos += 6;
                auto name_end = line.find("\"", name_pos);
                part.headers["name"] = line.substr(name_pos, name_end - name_pos);
            }

            auto filename_pos = line.find("filename=\"");
            if (filename_pos != std::string::npos) {
                filename_pos += 10;
                auto filename_end = line.find("\"", filename_pos);
                part.headers["filename"] = line.substr(filename_pos, filename_end - filename_pos);
            }
            break;
        }
        parts.push_back(part);
        start_pos = next_boundary_pos;
    }
    return parts;
}

// --- 文件上传 ---
void HttpHandlers::handleUpload(WFHttpTask *task) {
    auto user_opt = verify_token_and_get_user(task);
    if (!user_opt) { return; }

    const auto* req = task->get_req();
    protocol::HttpHeaderCursor cursor(req);

    std::string content_type_header, boundary;
    if (cursor.find("Content-Type", content_type_header) && content_type_header.find("boundary=") != std::string::npos) {
        boundary = content_type_header.substr(content_type_header.find("boundary=") + 9);
        if (boundary.front() == '"') boundary.erase(0, 1);
        if (boundary.back() == '"') boundary.pop_back();
    }
    if (boundary.empty()) {
        task->get_resp()->set_status_code("400");
        return;
    }

    const void* body_ptr; size_t body_len;
    req->get_parsed_body(&body_ptr, &body_len);
    std::string body(static_cast<const char*>(body_ptr), body_len);
    
    auto parts = parse_multipart_body(body, boundary);
    std::string filename, file_content;

    for(const auto& part : parts) {
        if(part.headers.count("name") && part.headers.at("name") == "file") {
            if (part.headers.count("filename")) {
                filename = part.headers.at("filename");
                file_content = part.content;
                break;
            }
        }
    }

    if (filename.empty() || file_content.empty()) {
        task->get_resp()->set_status_code("400");
        task->get_resp()->append_output_body(Response::jsonError("Bad Request: 'file' part is missing or invalid."));
        return;
    }

    FileInfo file_info;
    file_info.uid = user_opt->id;
    file_info.filename = filename;
    file_info.size = file_content.size();
    file_info.hashcode = Crypto::generateFileHash(file_content);   

    /////////////////////////////////////////////////////////////////////
    // multipart
    /////////////////////////////////////////////////////////////////////  

    // 定义永久存储路径

    FileUtils::createDirectory(Config::UPLOAD_PATH);
    std::string permanent_file_path = Config::UPLOAD_PATH + file_info.hashcode;

    // 将文件内容写入本地临时文件
    bool save_ok = FileUtils::saveFile(permanent_file_path, file_content);
    if (!save_ok) {
        task->get_resp()->set_status_code("500");
        task->get_resp()->append_output_body(Response::jsonError("Failed to save temporary file."));
        return;
    }

    // 在数据库中记录文件，状态“上传中”
    file_info.status = 0;  // 2: 上传中
    if (!FileDao::saveFile(file_info)) {
        task->get_resp()->set_status_code("500");
        task->get_resp()->append_output_body(Response::jsonError("Failed to save file metadata."));
        remove(permanent_file_path.c_str());
        return;
    }
    
    try {
        // 使用智能指针确保即使有异常也能正确关闭
        auto mq = std::make_unique<RabbitMQClient>(Config::RABBITMQ_URI, Config::RABBITMQ_EXCHANGE, Config::RABBITMQ_QUEUE, Config::RABBITMQ_ROUTING_KEY);
        
        json msg_json;
        msg_json["hashcode"] = file_info.hashcode;
        msg_json["local_path"] = permanent_file_path;
        
        if (!mq->publish(msg_json.dump())) {
            // 如果发送失败，记录错误，但可能不需要让用户知道，后台会有重试机制
            std::cerr << "Failed to publish message for hash: " << file_info.hashcode << std::endl;
        }
    } catch (const std::exception& e) {
        std::cerr << "Error connecting to RabbitMQ: " << e.what() << std::endl;
    }

    // 立即向用户返回成功
    task->get_resp()->append_output_body(Response::jsonSuccess({"message", "Upload request accepted."}));

}


// --- 文件查询 ---
void HttpHandlers::handleQuery(WFHttpTask *task) {
    auto user_opt = verify_token_and_get_user(task);
    if (!user_opt) { return; }

    auto files = FileDao::getFilesByUser(user_opt->id, 100);
    json file_list = json::array();
    for(const auto& f : files) {
        json file_json;
        file_json["id"] = f.id;
        file_json["filename"] = f.filename;
        file_json["size"] = f.size;
        file_json["hash"] = f.hashcode;
        file_json["created_at"] = f.created_at;
        file_list.push_back(file_json);
    }
    task->get_resp()->append_output_body(Response::jsonSuccess(file_list));
}


// --- 文件下载 ---
void HttpHandlers::handleDownload(WFHttpTask *task) {
    auto user_opt = verify_token_and_get_user(task);
    if (!user_opt) { return; }

    std::string path = task->get_req()->get_request_uri();
    std::string hashcode = path.substr(path.rfind('/') + 1);

    auto file_opt = FileDao::getFileByHashAndUser(hashcode, user_opt->id);
    if (!file_opt) {
        task->get_resp()->set_status_code("404");
        task->get_resp()->append_output_body(Response::jsonError("File not found or access denied."));
        return;
    }

    // --- 1. 尝试从本地主存储读取 (Fast Path) ---
    std::string file_path = Config::UPLOAD_PATH + hashcode;
    long long file_size = FileUtils::getFileSize(file_path);

    if (file_size >= 0) {
        // 本地文件存在，直接读取并发送
        char* buf = new char[file_size];
        auto* pread_task = WFTaskFactory::create_pread_task(file_path, buf, file_size, 0, 
            [task, buf, file_size, filename = file_opt->filename](WFFileIOTask *t) {
                if (t->get_retval() == file_size) {
                    task->get_resp()->append_output_body(buf, file_size);
                    task->get_resp()->add_header_pair("Content-Type", "application/octet-stream");
                    task->get_resp()->add_header_pair("Content-Disposition", "attachment; filename=\"" + filename + "\"");
                } else {
                    task->get_resp()->set_status_code("500");
                    task->get_resp()->append_output_body(Response::jsonError("Failed to read local file."));
                }
                delete[] buf;
            });
        series_of(task)->push_back(pread_task);
        return; // 结束处理
    }

    // --- 2. 本地文件不存在，启动B计划：从OSS备份中恢复 ---
    std::cout << "[INFO] Local file not found for hash: " << hashcode << ". Attempting to restore from OSS backup." << std::endl;
    
    auto content_stream_ptr = OssClientManager::getInstance()->downloadFile(hashcode);
    if (content_stream_ptr) {
        // 从OSS流中读取内容
        std::string content((std::istreambuf_iterator<char>(*content_stream_ptr)), std::istreambuf_iterator<char>());

        // 3. 将从OSS获取的内容返回给用户
        task->get_resp()->append_output_body(content.c_str(), content.length());
        task->get_resp()->add_header_pair("Content-Type", "application/octet-stream");
        task->get_resp()->add_header_pair("Content-Disposition", "attachment; filename=\"" + file_opt->filename + "\"");

        // 4. [自我修复] 将文件内容写回本地主存储，为下次下载做准备
        auto* pwrite_task = WFTaskFactory::create_pwrite_task(file_path, content.c_str(), content.length(), 0, 
            [hashcode](WFFileIOTask *t) {
                if (t->get_retval() < 0) {
                    std::cerr << "[ERROR] Failed to restore file from OSS to local storage for hash: " << hashcode << std::endl;
                } else {
                    std::cout << "[INFO] Successfully restored file to local storage: " << hashcode << std::endl;
                }
            });
        // 将写回任务加入后台执行，不阻塞当前下载请求
        series_of(task)->push_back(pwrite_task);

    } else {
        // 如果连OSS备份都找不到，那文件就真的丢失了
        task->get_resp()->set_status_code("404");
        task->get_resp()->append_output_body(Response::jsonError("File not found in both primary storage and backup."));
    }
}

// --- 文件删除 ---
void HttpHandlers::handleDelete(WFHttpTask *task) {
    auto user_opt = verify_token_and_get_user(task);
    if (!user_opt) { return; }

    const void* body; size_t size;
    task->get_req()->get_parsed_body(&body, &size);
    
    try {
        json req_json = json::parse(static_cast<const char*>(body), static_cast<const char*>(body) + size);
        int file_id = req_json.at("id");

        // 安全校验：此处应先查询数据库，确保该 file_id 属于该 user_id
        
        if (FileDao::deleteFile(file_id)) {
            task->get_resp()->append_output_body(Response::jsonSuccess({{"message", "File marked as deleted."}}));
        } else {
            task->get_resp()->set_status_code("500");
            task->get_resp()->append_output_body(Response::jsonError("Failed to delete file."));
        }
    } catch (const json::exception& e) {
        task->get_resp()->set_status_code("400");
        task->get_resp()->append_output_body(Response::jsonError("Invalid JSON format or missing 'id' field."));
    }
}
